# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: leon, chensili

import concurrent.futures
import datetime
import logging
import traceback

from absl import app, flags

from coin.base.param_util import to_list
from coin.base.datetime_util import (convert_string_to_dates, iterate_date)
from coin.exchange.kr_rest.product.product_impl \
    import get_exchange_product_list_grouped

from coin.strategy.mm.dumper_base import run_from_archive
from coin.support.feed_tool.feed_stats.logic.feed_stats_dumper \
    import DumpStrategy
from coin.strategy.mm.subscription import SubscriptionRequest
from coin.support.feed_tool.feed_stats.logic.util import (get_exchange_api_id_from_request,
                                                          fetch_git_commit_sha_datetime)
from coin.exchange.util.feed_checker import get_default_feed_checker_config
from coin.strategy.mm.subscription import FeedSubscriptionRequest

FLAGS = flags.FLAGS


def launch(products,
           trading_date,
           machine,
           git_commit_datetime,
           git_commit_sha,
           sub_request,
           print_result=False,
           db_config=None):
  # UTC 0 hour
  start_time = datetime.datetime.combine(trading_date, datetime.time.min)
  hours = 24
  end_time = start_time + datetime.timedelta(hours=hours)

  feed_checker_config = get_default_feed_checker_config(products)

  strategy = DumpStrategy(machine,
                          products,
                          trading_date,
                          start_time,
                          end_time,
                          git_commit_datetime,
                          git_commit_sha,
                          sub_request)

  feed_sub_request = FeedSubscriptionRequest()
  feed_sub_request.add_products(products, sub_request)

  run_from_archive(feed_sub_request,
                   strategy.on_feed_reset,
                   start_time,
                   end_time,
                   machine=[machine],
                   feed_checker_config=feed_checker_config)

  if print_result:
    strategy.print_book_stats()
    print('')
    strategy.print_trade_stats()
    print('')
    strategy.print_cross_stats()
    print('')
  if db_config:
    strategy.dump_to_db(db_config)

  return 0


def main(_):
  trading_date = FLAGS.trading_date
  assert trading_date, '--trading_date must be specified.'

  trading_date = datetime.datetime.strptime(trading_date, '%Y%m%d')
  machine = FLAGS.machine
  market_type = FLAGS.market_type
  exchange = FLAGS.exchange
  api_version = FLAGS.api_version
  if api_version == 'None':
    api_version = None

  db_config_file = FLAGS.db_config
  print_result = FLAGS.print_result
  max_workers = FLAGS.max_workers
  git_commit = FLAGS.git_commit

  git_commit_datetime, git_commit_sha = fetch_git_commit_sha_datetime(git_commit)

  td_str = trading_date.strftime('%Y-%m-%d')
  print('\nRunning for %s %s ...' % (machine, td_str))
  products = get_exchange_product_list_grouped(market_type, exchange, api_version, trading_date)
  sub_request = SubscriptionRequest(market_type, exchange, api_version)

  with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
    future_product_list = []
    for product_group in products:
      product_group = to_list(product_group)
      future = executor.submit(launch,
                               product_group,
                               trading_date,
                               machine,
                               git_commit_datetime,
                               git_commit_sha,
                               sub_request,
                               print_result,
                               db_config_file)
      future_product_list.append((future, product_group))
    for future, product_group in future_product_list:
      try:
        future.result()
      except ValueError as e:
        print('Fail to get feed stats.',
              machine,
              td_str,
              product_group[0].exchange,
              product_group,
              type(e),
              e)
        if (product_group[0].exchange == 'Bitflyer'
            and product_group[0].symbol in ('BCH-BTC.IMMEDIATE', 'ETH-BTC.IMMEDIATE')):
          pass
        else:
          print(traceback.format_exc())
      except Exception as e:
        print('Fail to get feed stats.',
              machine,
              td_str,
              product_group[0].exchange,
              product_group,
              type(e),
              e)
        print(traceback.format_exc())


if __name__ == '__main__':
  flags.DEFINE_string('trading_date', None, 'yyyymmdd')

  flags.DEFINE_string('machine', None, 'Machine name.')

  flags.DEFINE_string('market_type', None, 'Spot, Futures')

  flags.DEFINE_string('exchange', None, 'Exchange name.')

  flags.DEFINE_string('api_version', None, 'Api version')

  flags.DEFINE_bool('print_result', False, '')

  flags.DEFINE_string('db_config', None, 'Database config file.')

  flags.DEFINE_integer('max_workers', 1, 'Max number of workers.')

  flags.DEFINE_string('git_commit', 'HEAD', 'Git commit sha or HEAD.')

  logging.basicConfig(level='DEBUG', format='%(levelname)8s %(asctime)s %(name)s] %(message)s')

  app.run(main)
